package com.zyl.gather;

import com.zyl.backup.BackUp;
import com.zyl.backup.BackUpImpl;
import com.zyl.bean.Environment;
import com.zyl.log.Log;
import com.zyl.log.LogImpl;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * @version v1.0
 * @ProjectName: env_gather
 * @Package: com.zyl.gather
 * @ClassName: GatherImpl
 * @Description TODO(采集模块的接口实现类)
 * @Author 翟玉龙
 * @Date 2024/10/21-9:07
 */
public class GatherImpl implements Gather {

    // 备份数据对象的创建
    //private final BackUp backup = FactoryInstancePlus.getInstance("backup", BackUp.class);
    private final BackUp backup = new BackUpImpl();
    private static final String dataFile = "data-file-simple1";
    private static final String backUpFile = "backup/gather.backup";
    // 日志模块的实现类对象
    private final Log log = LogImpl.getInstance();

    @Override
    public List<Environment> gather() throws Exception {
        log.info("开始采集数据...........");
        // 读取文件的数据
        InputStream in = GatherImpl.class.getClassLoader()
                .getResourceAsStream(dataFile);
        if(in == null) {
            throw new RuntimeException("数据文件不存在!");
        }
        // 获取本次读取数据的字节数
        int count = in.available();
        // 使用BufferedReader 每次读取一整行数据
        BufferedReader br = new BufferedReader(new InputStreamReader(in));

        // 读取数据之前，查看备份文件是否存在
        if(new File(backUpFile).exists()) {
            // 存在则读取文件中的数据，然后跳过该数据
            Integer skipNum = backup.load(backUpFile, Integer.class, true);
            long skip = br.skip(skipNum);
            log.debug(String.format("本次跳过了%d个字节的数据", skip));
        }

        List<Environment> environments = new ArrayList<>();
        String line = null;
        // 循环读取文件中的数据
        while((line = br.readLine()) != null) {
            // 对每一行的数据进行解析
            // 100|101|2|16|1|3|5d606f7802|1|1516323596029
            String[] infos = line.split("[|]");
            if(infos.length != 9) {
                log.warn("采集到一条非环境数据" + line);
                // 跳过本条数据
                continue;
            }
            // 调用方法，将环境值数组数据转换为环境实体对象
            Environment env = initEnv(infos);
            // 根据传感器地址，进一步确定环境类型和环境数值
            switch (infos[3]) {
                case "16":
                    // 处理温湿度数据
                    env.setName("温度");
                    // 温度数据为数据前4位 , 需要转换的数据为16进制的字符串
                    int data = Integer.parseInt(infos[6].substring(0, 4), 16);
                    // 根据公式计算环境数值
                    float value = (data * (0.00268127F)) - 46.85F;
                    // 设置温度的数据
                    env.setData(value);

                    // 处理湿度数据 需要创建一个新的环境对象
                    Environment env2 = initEnv(infos);
                    env2.setName("湿度");
                    // 湿度数据为数据4-7位
                    int data2 = Integer.parseInt(infos[6].substring(4, 8), 16);
                    float value2 = (data2 * (0.00190735F)) - 6;
                    // 设置湿度的数据
                    env2.setData(value2);
                    // 将环境数据添加到集合中
                    environments.add(env2);
                    break;
                case "256":
                    // 处理光照强度数据
                    env.setName("光照强度");
                    env.setData(Integer.parseInt(infos[6].substring(0, 4), 16));
                    break;
                case "1280":
                    // 处理二氧化碳浓度数据
                    env.setName("二氧化碳");
                    env.setData(Integer.parseInt(infos[6].substring(0, 4), 16));
                    break;
                default:
                    // 当出现其他数值时 不符合需要处理的环境值 跳过处理
                    log.warn("该环境类型不在处理范围内：" + infos[3]);
                    continue;
            }
            environments.add(env);
        }
        log.info("数据采集完毕, 本次采集的数据条数为：" + environments.size());
        // 环境数据读取完毕后，将本次采集的数据字节数备份到文件中，以待下一次读取时跳过
        backup.store(backUpFile, count, false);

        // 关闭资源
        br.close();
        in.close();
        // 返回采集的结果数据
        return environments;
    }

    /**
     * 根据环境数值创建环境对象
     * @param infos 各项环境指标数值
     * @return 环境对象
     */
    private Environment initEnv(String[] infos) {
        Environment env = new Environment();
        // 给环境对象赋值
        env.setSrcId(infos[0])
                .setDesId(infos[1])
                .setDevId(infos[2])
                // 设置传感器地址
                .setSersorAddress(infos[3])
                .setCount(Integer.parseInt(infos[4]))
                .setCmd(infos[5])
                .setStatus(Integer.parseInt(infos[7]))
                // 处理时间戳 将其转为 Timestamp
                .setGatherDate(new Timestamp(Long.parseLong(infos[8])));
        return env;
    }
}
